package org.knot.mockejb3;

import java.io.Serializable;
import java.rmi.RemoteException;

import javax.ejb.*;
import org.apache.commons.logging.*;
import org.knot.mockejb3.interceptor.*;


/**
 * Performs exception logging and chaining according to the
 * EJB spec. Wraps system exceptions in RemoteException or EJBException. 
 * All runtime and transaction-related exceptions are considered system exceptions.
 * 
 * @see MockContainer#isSystemException(Throwable)
 *  
 */
public class EjbExceptionHandler  implements Aspect, Serializable {

    // logger for this class
    private static Log logger = LogFactory.getLog( EjbExceptionHandler.class.getName() );


    /**
     * Intercepts all EJB methods.
     * @see org.knot.mockejb3.interceptor.Aspect#getPointcut()
     */
    public Pointcut getPointcut(){
        
        return PointcutPair.or( new ClassPointcut( EJBObject.class, true), 
                new ClassPointcut( EJBLocalObject.class, true) );
    }
 
    /**
     * Performs exception translation according to the ejb spec rules.
     */
    public void intercept( InvocationContext invocationContext ) throws Exception {
        
        try {
            invocationContext.proceed();
        }
        catch ( Exception exception ){
            
            if ( MockContainer.isSystemException( exception ) ) {
                // According to the spec we must log the exception
                logger.error("\nException during invocation of "+
                        invocationContext.getTargetMethod(), exception);
                exception.printStackTrace();
                               
                throw new EJBException( exception );
            }
        
            throw exception;                     
            
        }
            
    }
    
    /**
     * This class does not have state, so all instances of this class
     * are considered equal
     */
    public boolean equals( Object obj ){
        
        if ( obj instanceof EjbExceptionHandler) 
            return true;
        else
            return false;
        
    }

    public int hashCode() { 
        return this.getClass().hashCode(); 
    }    
    
    

}
